/**
 *  NetLogo Double Discrete  Specification
 *
 * 
 *   @author NetLogo
 */


package model;

//TODO: What about GrayEncodedInteger Specifications? 
public strictfp class DoubleDiscreteSpec extends ParameterSpec {
	public double dMin;
	public double dStep;
	public double dMax;
	
	
	public DoubleDiscreteSpec(String name, double min, double step, double max) {
		super(name);
		dMin = min;
		dMax = max;
		dStep = step;
	}

// probably not needed
/*	public Double enforceValid(Object obj1) {
		return enforceValidDouble(((Double)obj1).doubleValue());
	}*/
	
	private double enforceValidDouble(double d)
	{
		if (d < dMin)
			d = dMin;
		else if (d > dMax)
			d = dMax;
		return  dMin + StrictMath.floor((d - dMin) / dStep) * dStep; 
	}

	@Override
	public long choiceCount()
	{
		return 1 + (long)StrictMath.floor((dMax - dMin)/dStep) ;
	}	

	@Override
	public String toString()
	{
		return "[ " + name + " [ " + dMin + " " + dStep + " " + dMax + " ]]";
	}

	@Override
	public Object getValueFromChoice( long choice , long maxNumChoices)
	{
		if (choice < choiceCount())
		{
			return new Double(dMin + dStep * choice);
		}
		else
		{
			// If the choice is greater than the choices, we assume this is because with bitstring representations, 
			// the maxNumChoices is the next power of 2 above choiceCount().
			// In this case, we try to spread out these "extra" choice settings across the whole range, since
			// this seems more fair than choosing all low settings.  
			// (Of course, some numbers are still more likely to be chosen than others, but that's unavoidable.) 
			long wrappedChoice = (long) StrictMath.round((double) (choice % choiceCount()) / (maxNumChoices - choiceCount()) * choiceCount());
			return new Double(dMin + dStep * wrappedChoice);
		}	
	}

}
